const electron = require('electron');
const { app, BrowserWindow, Menu, shell, ipcMain, protocol } = electron;
const { updater } = require('./updater');
const { Registry } = require('rage-edit');
const nurl = require('url');
const path = require('path');
const { supervisor } = require("koolearn-supervisor");

const { applyFlash } = require('./flash');

const { getSystemToken } = require('gsof-system-token');
const { analytics } = require('gsof-google-analytics');
const { applySettings } = require('./settings');
const notifications = require('./notifications');
const { parseInvokeProtocol } = require('./protocol');
const { Ipc } = require('./utils');

require('./tray');
require('./session');

const config = require('./config');

let menu;
let template;
let mainWindow = null;
let update;
let ua;
let closeall = false;
let _notifications = null;

const schemeName = 'koolearn';
const invokeProtocol = `${schemeName}://`;

global.appname = 'koolearn';

const { GLOBAL_APP_NAME, GLOBAL_APP_ID } = config;


const isWin = process.platform === 'win32';

if (process.argv.length > 0) {
    const url = process.argv.find(i => i.startsWith(invokeProtocol));
    if (url) {
        const invokeInfo = parseInvokeProtocol(url);
        if (invokeInfo) {
            process.env.INVOKE_INFO = invokeInfo;
        }
    }

    const wvDebug = process.argv.indexOf('--webview-debug');
    if (wvDebug >= 0) {
        process.env.WEBVIEW_DEBUG = !!wvDebug;
    }
}

applyFlash();
applySettings();

// 解决 cross-origin frame 问题
app.commandLine.appendSwitch('disable-site-isolation-trials');
// 视频软解
//app.commandLine.appendSwitch('disable-accelerated-video');
//app.allowRendererProcessReuse = false;

if (process.env.NODE_ENV === 'production') {
    const sourceMapSupport = require('source-map-support'); // eslint-disable-line
    sourceMapSupport.install();
}


if (process.env.NODE_ENV === 'production') {
    require('electron-debug')(); // eslint-disable-line global-require
    // eslint-disable-line
    const p = path.join(__dirname, '..', 'app', 'node_modules'); // eslint-disable-line
    require('module').globalPaths.push(p); // eslint-disable-line
}

const gotTheLock = app.requestSingleInstanceLock();

if (!gotTheLock) {
    app.quit();
    return;
}

supervisor.Instance.main({ url: "", ignoreHosts: [/metrics-report\..*koolearn.com/] });

app.on('second-instance', (event, commandLine, workingDirectory) => {
    // Someone tried to run a second instance, we should focus our window.
    if (mainWindow) {
        if (!mainWindow.isVisible()) {
            mainWindow.show();
        }

        if (mainWindow.isMinimized()) {
            mainWindow.restore();
        }

        mainWindow.focus();
    }

    const command = commandLine.find(i => i.startsWith(invokeProtocol));
    if (command) {
        console.log('protocol:', command);

        const invokeInfo = parseInvokeProtocol(command);
        if (!invokeInfo) {
            return;
        }

        mainWindow && mainWindow.webContents.send('protocol-client', invokeInfo);
    }
});

app.whenReady().then(() => {
    protocol.registerStringProtocol('koolearn', (request, callback) => {
        const invokeInfo = parseInvokeProtocol(request.url, true);
        console.log(invokeInfo);
        // if (invokeInfo) {
        //     mainWindow && mainWindow.webContents.send('protocol-client', invokeInfo);
        // }
        callback('');
    });

    _notifications = new notifications();

    _notifications.createWindow = () => {
        app.isReady() && createWindow();
    };
});


app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
        app.quit();
    }

    closeall = true;
});

app.on('activate', () => {
    app.isReady() && createWindow();
});

if (isWin) {
    isDefaultProtocolClient(schemeName, (isProtocol) => {
        if (!isProtocol) {
            setAsDefaultProtocolClient(schemeName);
        }
    });
} else {
    app.setAsDefaultProtocolClient(schemeName);
}

app.on('open-url', (event, url) => {
    event.preventDefault();

    if (!url || !url.startsWith(invokeProtocol)) {
        return;
    }

    const invokeInfo = parseInvokeProtocol(url);
    if (mainWindow && mainWindow.webContents) {
        mainWindow.webContents.send('protocol-client', invokeInfo);
    } else {
        process.env.INVOKE_INFO = invokeInfo;
        closeall && createWindow();
    }
});

const installExtensions = () => {
    // if (isWin && process.env.NODE_ENV === 'development') {
    //     const installer = require('electron-devtools-installer'); // eslint-disable-line global-require

    //     const extensions = [
    //         'REACT_DEVELOPER_TOOLS',
    //     ];
    //     const forceDownload = !!process.env.UPGRADE_EXTENSIONS;
    //     return Promise.all(extensions.map(name => installer.default(installer[name], forceDownload)));
    // }

    return Promise.resolve([]);
};

var _analytics;
const package = require('../package.json');
const version = package.version;

console.log(`analytics version: ${version}`);

function analysics(params, callback) {
    getSystemToken().then((token) => {
        global.deviceId = token; //为了日志上报纪录
        const window = mainWindow;
        ua = ua || (window.webContents.getUserAgent() || '').replace(GLOBAL_APP_NAME, 'koolearn');
        ua && window.webContents.setUserAgent(ua);

        console.log(`User Agent: ${ua}`);
        const {
            width,
            height
        } = electron.screen.getPrimaryDisplay().size;

        if (!_analytics) {
            _analytics = new analytics('UA-16054642-7', token.toLowerCase(), ua);
        }

        const name = isWin ? 'koolearn-windows' : 'koolearn-mac';
        const appid = isWin ? 'com.koolearn.windows' : 'com.koolearn.mac';

        console.log(`token:${token.toLowerCase()}`);
        console.log('\n\n');


        _analytics
            .screenview(name, version, appid, appid, 'APP')
            .append(Object.assign({
                sr: `${width}x${height}`,
                ul: app.getLocale(),
            }, params))
            .send().then((json) => {
                if (json) {
                    console.log(`google analytics debug: ${json}`);
                }
                callback && callback();
            }).catch((e) => {
                console.log(`google analytics error: ${e}`);
            });
    });
}
console.log('appid:', GLOBAL_APP_ID);
app.setAppUserModelId(GLOBAL_APP_ID);

app.on('ready', () => {
    installExtensions()
        .then(() => {
            createWindow();
        });
});


app.on('before-quit', () => {
    console.log('before-quit');
    analysics({
        sc: 'end'
    });
});


app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
    if (process.argv.indexOf('--webview-debug') < 0 && process.argv.indexOf('--ignore-certificate')) {
        return;
    }

    if ((certificate.subjectName || '').endsWith('koolearn.com') && (certificate.serialNumber || '').toLowerCase() === '1d03337187ca451fb337a275') {
        event.preventDefault();
        callback(true);
    }
});


function createWindow() {
    if (mainWindow) {
        return;
    }

    const opts = {
        show: false,
        width: 560,
        height: 360,
        frame: false,
        resizable: true,
        title: GLOBAL_APP_NAME,
        webPreferences: {
            nodeIntegration: true,
            webviewTag: true,
            enableRemoteModule: true,
        }
    };

    if (!isWin) {
        // opts.ackgroundColor: '#2e2c29',
        opts.vibrancy = 'appearance-based';
        opts.titleBarStyle = 'hiddenInset';
    }

    global.mainWindow = mainWindow = new BrowserWindow(opts);
    closeall = false;

    // update = new updater();
    // update.setWindow(mainWindow);

    mainWindow.loadURL(`file://${__dirname}/../app.html`);

    mainWindow.webContents.openDevTools();

    mainWindow.webContents.on('did-finish-load', () => {
        mainWindow.show();
        mainWindow.focus();
    });

    mainWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription, validatedURL, isMainFrame) => {
        console.log(errorCode);
        console.log(errorDescription);
        console.log(validatedURL);
        console.log(isMainFrame);
        mainWindow.show();
        mainWindow.focus();
    });

    mainWindow.on('closed', () => {
        global.mainWindow = mainWindow = null;
        if (update) {
            //update.destroy();
        }
        update = null;
        console.log('window closed');
    });

    mainWindow.on('show', () => {
        mainWindow.center();
        // update.setWindow(mainWindow);
        // setTimeout(() => {
        //     update && update.checkUpdates(), 6000
        // });
    });

    analysics({
        sc: 'start'
    });

    if (process.env.NODE_ENV === 'production') {
        mainWindow.openDevTools({
            mode: ''
        });
        mainWindow.webContents.on('context-menu', (e, props) => {
            const { x, y } = props;

            Menu.buildFromTemplate([{
                label: 'Inspect element',
                click() {
                    mainWindow.inspectElement(x, y);
                }
            }]).popup(mainWindow);
        });
    } else if (process.env.OPEN_DEV) {
        mainWindow.openDevTools({
            mode: 'detach'
        });
    }


    if (process.platform === 'darwin') {
        template = [{
            label: GLOBAL_APP_NAME,
            submenu: [{
                label: '关于',
                selector: 'orderFrontStandardAboutPanel:'
            }, {
                type: 'separator'
            }, {
                label: '退出',
                accelerator: 'Command+Q',
                click() {
                    app.quit();
                }
            }]
        }, {
            label: '编辑',
            submenu: [{
                label: '撤销',
                accelerator: 'Command+Z',
                selector: 'undo:'
            }, {
                label: '重做',
                accelerator: 'Shift+Command+Z',
                selector: 'redo:'
            }, {
                type: 'separator'
            }, {
                label: '剪切',
                accelerator: 'Command+X',
                selector: 'cut:'
            }, {
                label: '复制',
                accelerator: 'Command+C',
                selector: 'copy:'
            }, {
                label: '粘贴',
                accelerator: 'Command+V',
                selector: 'paste:'
            }, {
                label: '全选',
                accelerator: 'Command+A',
                selector: 'selectAll:'
            }]
        }];

        menu = Menu.buildFromTemplate(template);
        Menu.setApplicationMenu(menu);
    } else {
        template = [{
            label: '&File',
            submenu: [{
                label: '&Open',
                accelerator: 'Ctrl+O'
            }, {
                label: '&Close',
                accelerator: 'Ctrl+W',
                click() {
                    mainWindow.close();
                }
            }]
        }, {
            label: '&View',
            submenu: (process.env.NODE_ENV === 'production') ? [{
                label: '&Reload',
                accelerator: 'Ctrl+R',
                click() {
                    mainWindow.webContents.reload();
                }
            }, {
                label: 'Toggle &Full Screen',
                accelerator: 'F11',
                click() {
                    mainWindow.setFullScreen(!mainWindow.isFullScreen());
                }
            }, {
                label: 'Toggle &Developer Tools',
                accelerator: 'Alt+Ctrl+I',
                click() {
                    mainWindow.toggleDevTools();
                }
            }] : [{
                label: 'Toggle &Full Screen',
                accelerator: 'F11',
                click() {
                    mainWindow.setFullScreen(!mainWindow.isFullScreen());
                }
            }]
        }, {
            label: 'Help',
            submenu: [{
                label: 'Learn More',
                click() {
                    shell.openExternal('http://electron.atom.io');
                }
            }, {
                label: 'Documentation',
                click() {
                    shell.openExternal('https://github.com/atom/electron/tree/master/docs#readme');
                }
            }, {
                label: 'Community Discussions',
                click() {
                    shell.openExternal('https://discuss.atom.io/c/electron');
                }
            }, {
                label: 'Search Issues',
                click() {
                    shell.openExternal('https://github.com/atom/electron/issues');
                }
            }]
        }];
        //menu = Menu.buildFromTemplate(template);
        mainWindow.setMenu(null);
    }
}

global.createWindow = () => {
    app.isReady() && createWindow();
};

ipcMain.once('new-updater', (event, arg) => {
    if (update) {
        return;
    }
    console.log('new-updater');
    update = global.update = new updater(arg);
    //setTimeout(() => ut.checkUpdates(), 30000);
});

ipcMain.on('newDownloadTask', webContentDownload);

// function tokenResolve(url) {
//     if (!url || !url.startsWith(`${schemeName}://`)) {
//         return '';
//     }

//     let token = url.substr(schemeName.length + 3);
//     if (token.endsWith('/')) {
//         token = token.substr(0, token.length - 1);
//     }

//     return token;
// }



function setAsDefaultProtocolClient(protocol) {
    const exePath = app.getPath('exe');
    Registry.set(`HKCU\\SOFTWARE\\Classes\\${protocol}`, '', GLOBAL_APP_NAME)
        .then(Registry.set(`HKCU\\SOFTWARE\\Classes\\${protocol}`, 'URL Protocol'))
        .then(Registry.set(`HKCU\\SOFTWARE\\Classes\\${protocol}\\DefaultIcon`, '', `${exePath}`))
        .then(Registry.set(`HKCU\\SOFTWARE\\Classes\\${protocol}\\shell`))
        .then(Registry.set(`HKCU\\SOFTWARE\\Classes\\${protocol}\\shell\\open`))
        .then(Registry.set(`HKCU\\SOFTWARE\\Classes\\${protocol}\\shell\\open\\command`, '', `"${exePath}" "%1"`));
}

function isDefaultProtocolClient(protocol, callback) {
    Registry.has(`HKCR\\${protocol}`).then((value) => {
        console.log(value);
        callback(value);
    }).catch((err) => {
        console.log('isDefaultProtocolClient', err);
        callback(false);
    });
}


function webContentDownload(event, url) {
    if (!mainWindow || !mainWindow.webContents) {
        event.reply('newDownloadTask-reply', url, -1);
        return;
    }

    mainWindow.webContents.session.removeListener('will-download', webContentWillDownload);
    mainWindow.webContents.session.on('will-download', webContentWillDownload);
    mainWindow.webContents.downloadURL(url);
    event.reply('newDownloadTask-reply', url, 0);
}

function webContentWillDownload(event, item, webContents) {
    const option = item.getSaveDialogOptions();
    option.title = '保存';
    item.setSaveDialogOptions(option);

    item.on('updated', (event, state) => {
        if (state === 'interrupted') {
            webContentSendStatus(item, 'interrupted');
        } else if (state === 'progressing') {
            if (item.isPaused()) {
                webContentSendStatus(item, 'paused');
            } else {
                webContentSendStatus(item, 'progressing');
            }
        }
    });
    item.once('done', (event, state) => {
        if (state === 'completed') {
            webContentSendStatus(item, 'completed');
        } else if (state === 'cancelled') {
            webContentSendStatus(item, 'cancelled');
        } else {
            webContentSendStatus(item, 'failed');
        }
    });
}

function webContentSendStatus(item, status) {
    mainWindow.webContents.send('webContentDownload', item.getURL(), status, item.getReceivedBytes(), item.getTotalBytes());
}